HAL SDIO Typical use cases for migration

This section provides information about the HAL SDIO Typical use cases for migration.

Note

The main SDIO API usage patterns—such as direct and extended transfers (polling or DMA), and function interrupt handling—remain largely unchanged for the user between HAL1 and HAL2. Most function names and parameters remain unchanged.

The most significant changes in HAL2 are in the card identification sequence during initialization, and also the callback registration and handling:

  • Configuration and card identification: In HAL1, the custom card identification required callback registration (see use case description for details); in HAL2, the identification function is passed as a pointer parameter to the configuration API HAL_SDIO_SetConfig().

  • Callback registration is unified and event-driven: Instead of separate TX and RX callbacks, HAL2 introduces a single transfer completion callback with an event parameter.

Use case: SDIO configuration and card identification sequence

The card identification function performs communication with the SDIO card and extracts the card’s key information, needed before applying the user configurations and starting operation. Users can provide a custom identification sequence to handle device-specific requirements or vendor extensions that differ from the default flow.

HAL1

HAL2

In HAL1 (Callback Registration): User used to register his custom card identification function using HAL_SDIO_RegisterIdentifyCardCallback(). The driver then executed this callback internally during the HAL_SDIO_Init() function. If not registered, the driver used the default identification sequence.

In HAL2 (Direct Parameter): The sequence is changed, there is no registration step and the user should pass the identification function directly as the third argument to HAL_SDIO_SetConfig(). Passing NULL instructs the driver to use the default identification sequence.

@startuml
hide footbox
participant "User Application" as part1
participant "HAL SDIO" as part2
activate part1
activate part2

group Identify card callback registration
alt USER_SDIO_USE_CUSTOM_IDENTIFY defined
        part1 -> part2 : HAL_SDIO_RegisterIdentifyCardCallback(&hsdio, USER_SDIO_IdentifyCard)
        part2 --> part1
else Default identify
        part1 --> part1
        note right
            Do nothing to use the default implementation
        end note
end
end

group Initialization & Configuration
        part1->part2 : HAL_SDIO_Init(&hsdio)
        part2-->part1 : HAL Status
end
@enduml

Code Snippet

HAL1

HAL2

hsdio.Instance = SDMMC1;
hsdio.Init = user_sdio_config;

/* Register custom card identification function if needed */
#if defined(USER_SDIO_USE_CUSTOM_IDENTIFY)
/* Register custom card identification function */
HAL_SDIO_RegisterIdentifyCardCallback(&hsdio,
                                      USER_SDIO_IdentifyCard);

#else
/* Do nothing; use default card identification */
#endif

/* Continue with SDIO initialization and configuration */
HAL_SDIO_Init(&hsdio);


HAL_StatusTypeDef USER_SDIO_IdentifyCard(SDIO_HandleTypeDef *hsdio)
{
    /* Custom card identification sequence */
    .
    ..
    ...
    return HAL_OK;
}
/* Perform SDIO driver initialization */
HAL_SDIO_Init(&hsdio, HAL_SDIO_CARD_1);

/* Perform SDIO configuration */
#if defined(USER_SDIO_USE_CUSTOM_IDENTIFY)
/* Provide custom identify card function */
HAL_SDIO_SetConfig(&hsdio,
                   &user_sdio_config,
                   USER_SDIO_IdentifyCard);
#else
/* Pass NULL as third param; use default card identification */
HAL_SDIO_SetConfig(&hsdio, &user_sdio_config, NULL);
#endif




hal_status_t USER_SDIO_IdentifyCard(hal_sdio_handle_t *hsdio)
{
    /* Custom card identification sequence */
    .
    ..
    ...
    return HAL_OK;
}

Use case: SDIO direct transfer

A direct I/O transfer accesses a single byte in an SDIO function register space and is commonly used for control/status registers (for example, reading an interrupt status register or writing a configuration value). The sequence and APIs remain unchanged between HAL1 and HAL2.

For example, an SDIO Wi‑Fi device may expose multiple functions where user_io_func_nbr selects the Wi‑Fi function; a direct transfer could then read a status register in the Wi‑Fi function or write a control register.

@startuml
hide footbox
participant "User Application" as part1
participant "HAL SDIO" as part2
activate part1
activate part2

group Direct I/O access
part1->part2 : HAL_SDIO_ReadDirect()
part2-->part1 : HAL Status
part1->part2 : HAL_SDIO_WriteDirect()
part2-->part1 : HAL Status
end
@enduml

Code Snippet

HAL1/HAL2

uint8_t reg_value = 0U;

/* Read a single byte from a function register */
if (HAL_SDIO_ReadDirect(&hsdio,
                        user_io_func_nbr,
                        RegisterAddress,
                        &reg_value) != HAL_OK)
{
   Error_Handler();
}

/* Update configuration register */
reg_value |= REG_ENABLE_MASK; /* Example: enable a specific feature */

/* Write back the updated value to the function register */
if (HAL_SDIO_WriteDirect(&hsdio,
                         user_io_func_nbr,
                         RegisterAddress,
                         reg_value) != HAL_OK)
{
   Error_Handler();
}

Use case: SDIO extended polling transfer

Extended polling transfers use HAL_SDIO_WriteExtended() and HAL_SDIO_ReadExtended() in blocking mode. The APIs remain unchanged between HAL1 and HAL2. For example, an SDIO Wi‑Fi device may expose multiple functions where user_io_func_nbr selects the Wi‑Fi function; an extended transfer could then transfer a TCP/IP packet in the Wi‑Fi function.

@startuml
hide footbox
participant "User Application" as part1
participant "HAL SDIO" as part2
activate part1
activate part2

group Extended polling I/O access
part1->part2 : HAL_SDIO_WriteExtended()
part2-->part1 : HAL Status
part1->part2 : HAL_SDIO_ReadExtended()
part2-->part1 : HAL Status
end
@enduml

Code Snippet

HAL1/HAL2

/* Write BufferSize bytes to function user_io_func_nbr
    at address IoAddress using Extended polling */
if (HAL_SDIO_WriteExtended(&hsdio,
                           user_io_func_nbr,
                           Write_IoAddress,
                           Buffer_Tx,
                           BufferSize,
                           TimeoutMs) != HAL_OK)
{
    Error_Handler();
}

/* Read BufferSize bytes from function user_io_func_nbr
    at address IoAddress using Extended polling */
if (HAL_SDIO_ReadExtended(&hsdio,
                          user_io_func_nbr,
                          Read_IoAddress,
                          Buffer_Rx,
                          BufferSize,
                          TimeoutMs) != HAL_OK)
{
    Error_Handler();
}

Use case: SDIO extended DMA transfer

The extended DMA transfer uses interrupts to handle transfer completion and errors. The sequence and APIs remain mostly unchanged between HAL1 and HAL2, with only changes in the callback registration and handling.

An SDIO Wi‑Fi device may expose multiple functions where user_io_func_nbr selects the Wi‑Fi function; an extended transfer could then transfer a TCP/IP packet in the Wi‑Fi function.

HAL1

HAL2

Extended DMA transfer uses HAL_SDIO_WriteExtended_DMA() and HAL_SDIO_ReadExtended_DMA() for non-blocking I/O. Transfer completion is reported via separate TX/RX callbacks registered with HAL_SDIO_RegisterCallback().

Extended DMA transfer sequence is mostly unchanged, but callback registration is unified through HAL_SDIO_RegisterXferCpltCallback(), registering only one transfer callback which delivers both TX and RX events using an event parameter.

@startuml
hide footbox
participant "User Application" as part1
participant "HAL SDIO" as part2
participant "NVIC" as part3
activate part1
activate part2

group Register transfer complete callbacks
part1->part2 : HAL_SDIO_RegisterCallback(&hsdio, HAL_SDIO_TX_CPLT_CB_ID, USER_SDIO_TxCpltCallback)
part2 --> part1
part1->part2 : HAL_SDIO_RegisterCallback(&hsdio, HAL_SDIO_RX_CPLT_CB_ID, USER_SDIO_RxCpltCallback)
part2 --> part1
end

group I/O Operation process (Extended DMA)
part1->part2 : HAL_SDIO_WriteExtended_DMA()
part2-->part1
part3 -> part2 : HAL_SDIO_IRQHandler()
part2 -> part1 : USER_SDIO_TxCpltCallback()
part1->part2 : HAL_SDIO_ReadExtended_DMA()
part2-->part1
part3 -> part2 : HAL_SDIO_IRQHandler()
part2 -> part1 : USER_SDIO_RxCpltCallback()
end
@enduml

Code Snippet

HAL1

HAL2

/* Register the Tx and Rx Transfer complete callbacks */
HAL_SDIO_RegisterCallback(&hsdio,
                          HAL_SDIO_TX_CPLT_CB_ID,
                          USER_SDIO_TxCpltCallback);
HAL_SDIO_RegisterCallback(&hsdio,
                          HAL_SDIO_RX_CPLT_CB_ID,
                          USER_SDIO_RxCpltCallback);

/* Write BufferSize bytes to function user_io_func_nbr
    at address IoAddress using Extended DMA */
HAL_SDIO_WriteExtended_DMA(&hsdio,
                           user_io_func_nbr,
                           Write_IoAddress,
                           Buffer_Tx,
                           BufferSize);
/* Wait for the Writing process to complete */
while (sdiotransfertx == 0)
{}
 /* Read BufferSize bytes from function user_io_func_nbr
     at address IoAddress using Extended DMA */
 HAL_SDIO_ReadExtended_DMA(&hsdio,
                           user_io_func_nbr,
                           ReadIoAddress,
                           Buffer_Rx,
                           BufferSize);
/* Wait for the Reading process to complete */
while (sdiotransferrx == 0)
{}


void USER_SDIO_TxCpltCallback(SDIO_HandleTypeDef *hsdio) {
    sdiotransfertx = 1;
}

void USER_SDIO_RxCpltCallback(SDIO_HandleTypeDef *hsdio) {
    sdiotransferrx = 1;
}
/* Register the Tx and Rx Transfer complete callbacks */
HAL_SDIO_RegisterXferCpltCallback(&hsdio,
                                  USER_SDIO_XferCallback);





/* Write BufferSize bytes to function user_io_func_nbr
    at address IoAddress using Extended DMA */
HAL_SDIO_WriteExtended_DMA(&hsdio,
                           user_io_func_nbr,
                           Write_IoAddress,
                           Buffer_Tx,
                           BufferSize);
/* Wait for the Writing process to complete */
while (sdiotransfertx == 0)
{}
/* Read BufferSize bytes from function user_io_func_nbr
    at address IoAddress using Extended DMA */
HAL_SDIO_ReadExtended_DMA(&hsdio,
                          user_io_func_nbr,
                          Read_IoAddress,
                          Buffer_Rx,
                          BufferSize);
/* Wait for the Reading process to complete */
while (sdiotransferrx == 0)
{}


void USER_SDIO_XferCallback(hal_sdio_handle_t *hsdio,
                            hal_sdio_event_cb_t cb_event) {
    switch (cb_event) {
        case HAL_SDIO_EVENT_CB_TX_CPLT:
        sdiotransfertx = 1;
        break;
        case HAL_SDIO_EVENT_CB_RX_CPLT:
        sdiotransferrx = 1;
        break;
        default: break;
    }
}